#include "../include/BuildSym.h"

int gvNum;
int lvNum;
int fNum;
int vAdr = 2;//adr初值

BuildSym gv[symMax];//全局变量符号表
BuildSym lv[symMax];//局部变量符号表
BuildSym func[symMax];//函数符号表
bool global = true;

void BuildSym::visit(VarDef *) {
    if (global) {
        for (int i = 0; i < gvNum; i++) {
            if (strcmp(node->left->strValue, gv[i].name) == 0) {
                cerr << " Redefinition of '" << node->left->strValue << "' as different kind of symbol" << endl;
                exit(5);
            }
        }
        for (int i = 0; i < fNum; i++) {
            if (strcmp(node->left->strValue, func[i].name) == 0) {
                cerr << "Redefinition of '" << node->left->strValue << "' as different kind of symbol" << endl;
                exit(5);
            }
        }
        gv[gvNum].kind = (char *) "variable";
        gv[gvNum].scope = (char *) "global";
        gv[gvNum].typeGLF = whichVarDecl;
        gv[gvNum].name = node->left->strValue;
        gv[gvNum].adr = vAdr++;
        gvNum++;
        return;
    } else {
        lv[lvNum].level = 0;
        lv[lvNum].kind = (char *) "variable";
        lv[lvNum].scope = whichFunc;
        lv[lvNum].typeGLF = whichVarDecl;
        lv[lvNum].name = node->left->strValue;
        lv[lvNum].adr = func[fNum - 1].size++;
        lvNum++;
    }
}

void BuildSym::visit(FuncDef *) {
    global = false;
    vAdr = 2;
    for (int k = 0; k < gvNum; k++) {
        if (strcmp(node->left->left->next->strValue, gv[k].name) == 0) {
            cerr << " Redefinition of '" << node->left->left->next->strValue << "' as different kind of symbol" << endl;
            exit(5);
        }
    }
    for (int j = 0; j < fNum; j++) {
        if (strcmp(node->left->left->next->strValue, func[j].name) == 0) {
            cerr << " Redefinition of '" << node->left->left->next->strValue << "' as different kind of symbol" << endl;
            exit(5);
        }
    }
    func[fNum].kind = (char *) "function";
    func[fNum].typeGLF = node->left->left->strValue;
    func[fNum].level = 1;
    func[fNum].name = node->left->left->next->strValue;
    whichFunc = node->left->left->next->strValue;
    fNum++;
}

void BuildSym::visit(UnaryExp *) {
    for (int i = 0; i < fNum; i++) {
        if (strcmp(node->left->strValue, func[i].name) == 0) {
            if (!func[i].hasBeenCalled) {
                func[i].level++;
                func[i].hasBeenCalled = true;
                for (int j = 0; j < lvNum; j++) {
                    if (strcmp(lv[j].scope, func[i].name) == 0) {
                        lv[j].level = func[i].level;
                    }
                }
            }
        }
    }
}

void BuildSym::visit(Block_list *) {
    func[fNum - 1].blockList = node->ivalue;
}

void BuildSym::visit(VarDecl *) {
    whichVarDecl=node->left->strValue;
}

[[maybe_unused]] void BuildSym::showSym() {
    for (int i = 0; i < gvNum; i++) {
        cout << "name:" << gv[i].name << "    kind:" << gv[i].kind << "    level:" << "0" << "    addr:" << gv[i].adr
             << "    作用域:" << gv[i].scope
             << endl;
    }
    for (int i = 0; i < lvNum; i++) {
        cout << "name:" << lv[i].name << "    kind:" << lv[i].kind << "    level:" << lv[i].level << "    addr:"
             << lv[i].adr
             << "    作用域:" << lv[i].scope
             << endl;
    }
    for (int i = 0; i < fNum; i++) {
        cout << "name:" << func[i].name << "    kind:" << func[i].kind << "    level:" << func[i].level << "    addr:"
             << "" << endl;
    }
}

